home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / programr / upc12bs2.zip / RNEWS / expire.c next >
C/C++ Source or Header  |  1993-07-12  |  20KB  |  540 lines

  1. /*--------------------------------------------------------------------*/
  2. /*    e x p i r e . c                                                 */
  3. /*                                                                    */
  4. /*    Expire old news articles for UUPC/extended                      */
  5. /*                                                                    */
  6. /*    Copyright (c) 1992-1993 by Kendra Electronic Wonderworks, all   */
  7. /*    rights reserved except those explicitly granted by the UUPC/    */
  8. /*    extended license.                                               */
  9. /*--------------------------------------------------------------------*/
  10.  
  11. /*
  12.  *    $Id: expire.c 1.5 1993/07/13 01:13:32 ahd Exp $
  13.  *
  14.  *    $Log: expire.c $
  15.  * Revision 1.5  1993/07/13  01:13:32  ahd
  16.  * Drop unused stater.h header
  17.  *
  18.  * Revision 1.4  1993/04/05  04:32:19  ahd
  19.  * Add timestamp, size to information returned by directory searches
  20.  *
  21.  * Revision 1.3  1992/11/25  12:59:17  ahd
  22.  * Modifiy summery messages
  23.  *
  24.  */
  25.  
  26. /*--------------------------------------------------------------------*/
  27. /*                        System include files                        */
  28. /*--------------------------------------------------------------------*/
  29.  
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <string.h>
  33. #include <ctype.h>
  34. #include <time.h>
  35. #include <limits.h>
  36.  
  37. /*--------------------------------------------------------------------*/
  38. /*                    UUPC/extended include files                     */
  39. /*--------------------------------------------------------------------*/
  40.  
  41. #include "lib.h"
  42. #include "active.h"
  43. #include "dater.h"
  44. #include "getopt.h"
  45. #include "hlib.h"
  46. #include "import.h"
  47. #include "importng.h"
  48. #include "logger.h"
  49. #include "uundir.h"
  50. #include "pushpop.h"
  51. #include "timestmp.h"
  52.  
  53. currentfile();
  54.  
  55. /*--------------------------------------------------------------------*/
  56. /*                          Global Variables                          */
  57. /*--------------------------------------------------------------------*/
  58.  
  59. #define ONE_DAY (60L*60L*24L)
  60.  
  61. /*--------------------------------------------------------------------*/
  62. /*                        Internal prototypes                         */
  63. /*--------------------------------------------------------------------*/
  64.  
  65. static boolean numeric( char *start);
  66.  
  67. static void ExpireAll( const time_t expire_date,
  68.                        const time_t archive_date );
  69.  
  70. static void  ExpireGroup( const char *group,
  71.                       const time_t expire_date,
  72.                       const time_t archive_date );
  73.  
  74. static void ExpireOneGroup( struct grp *cur_grp,
  75.                       const time_t expire_date,
  76.                       const time_t archive_date );
  77.  
  78. static void ExpireDirectory( struct grp *cur_grp,
  79.                       const time_t expire_date,
  80.                       const char *directory,
  81.                       const char *archive );
  82.  
  83. static boolean numeric( char *start);
  84.  
  85. static void usage( void );
  86.  
  87. long total_articles_purged   = 0;
  88. long total_articles_archived = 0;
  89. long total_articles_kept     = 0;
  90. long total_bytes_purged   = 0;
  91. long total_bytes_archived = 0;
  92. long total_bytes_kept     = 0;
  93.  
  94. /*--------------------------------------------------------------------*/
  95. /*    m a i n                                                         */
  96. /*                                                                    */
  97. /*    Main program                                                    */
  98. /*--------------------------------------------------------------------*/
  99.  
  100. void main( int argc, char **argv)
  101. {
  102.    int c;
  103.    extern char *optarg;
  104.    extern int   optind;
  105.    char *group = NULL;
  106.  
  107.    time_t expire_period  = 7; /* Seven days visible to users         */
  108.    time_t archive_period = 0; /* Seven days after expiring in arch   */
  109.  
  110.    time_t expire_date;
  111.    time_t archive_date;
  112.  
  113. /*--------------------------------------------------------------------*/
  114. /*     Report our version number and date/time compiled               */
  115. /*--------------------------------------------------------------------*/
  116.  
  117.    debuglevel = 1;
  118.    banner( argv );
  119.  
  120. #if defined(__CORE__)
  121.    copywrong = strdup(copyright);
  122.    checkref(copywrong);
  123. #endif
  124.  
  125. /*--------------------------------------------------------------------*/
  126. /*        Process our arguments                                       */
  127. /*--------------------------------------------------------------------*/
  128.  
  129.    while ((c = getopt(argc, argv, "e:a:g:x:n:")) !=  EOF)
  130.       switch(c) {
  131.  
  132.       case 'a':
  133.          archive_period = atoi( optarg );
  134.          break;
  135.  
  136.       case 'e':
  137.          expire_period = atoi( optarg );
  138.          break;
  139.  
  140.       case 'n':
  141.          group = optarg;
  142.          break;
  143.  
  144.       case 'x':
  145.          debuglevel = atoi( optarg );
  146.          break;
  147.  
  148.       case '?':
  149.          usage();
  150.          exit(1);
  151.          break;
  152.  
  153.       default:
  154.          printmsg(0, "expire - invalid option -%c", c);
  155.          usage();
  156.          exit(2);
  157.          break;
  158.    }
  159.  
  160.    if (optind != argc) {
  161.       fputs("Extra parameter(s) at end.\n", stderr);
  162.       usage();
  163.       exit(2);
  164.    }
  165.  
  166. /*--------------------------------------------------------------------*/
  167. /*                             Initialize                             */
  168. /*--------------------------------------------------------------------*/
  169.  
  170.    tzset();                      /* Set up time zone information  */
  171.  
  172.    if (!configure( B_NEWS ))
  173.       exit(1);   /* system configuration failed */
  174.  
  175. /*--------------------------------------------------------------------*/
  176. /*                  Switch to the spooling directory                  */
  177. /*--------------------------------------------------------------------*/
  178.  
  179.    PushDir( E_newsdir );
  180.    atexit( PopDir );
  181.  
  182. /*--------------------------------------------------------------------*/
  183. /*                     Initialize logging file                        */
  184. /*--------------------------------------------------------------------*/
  185.  
  186.    openlog( NULL );
  187.  
  188. /*--------------------------------------------------------------------*/
  189. /*                       Load the active file                         */
  190. /*--------------------------------------------------------------------*/
  191.  
  192.    get_active();              /* Get sequence numbers for groups from
  193.                                  active file                      */
  194.  
  195. /*--------------------------------------------------------------------*/
  196. /*                  Compute times for expiring files                  */
  197. /*--------------------------------------------------------------------*/
  198.  
  199.    time( &expire_date );
  200.    expire_date  -= (expire_period * ONE_DAY);
  201.    archive_date = expire_date - (archive_period * ONE_DAY);
  202.  
  203.    printmsg(1,"%s: %sing news older than %s (%ld days)",
  204.             argv[0],
  205.             archive_period ?  "Archiv" : "Purg",
  206.             dater( expire_date , NULL), (long) expire_period );
  207.  
  208.    if ( archive_period != 0 )
  209.       printmsg(1,"%s: Purging news older than %s",
  210.             argv[0],
  211.                   dater( archive_date , NULL));
  212.  
  213. /*--------------------------------------------------------------------*/
  214. /*    Process one group if requested, otherwise process the entire    */
  215. /*    active file                                                     */
  216. /*--------------------------------------------------------------------*/
  217.  
  218.       if ( group != NULL )
  219.          ExpireGroup( group, expire_date, archive_date );
  220.       else
  221.          ExpireAll(expire_date, archive_date );
  222.  
  223. /*--------------------------------------------------------------------*/
  224. /*                         Clean up and exit                          */
  225. /*--------------------------------------------------------------------*/
  226.  
  227.    put_active();
  228.  
  229.    if ( total_articles_purged || total_articles_archived)
  230.       printmsg(1,"%s: Purged %ld total articles (%ld bytes), "
  231.                     "archived %ld total articles (%ld bytes). " ,
  232.                   argv[0],
  233.                   total_articles_purged,   total_bytes_purged,
  234.                   total_articles_archived, total_bytes_archived );
  235.  
  236.    printmsg(1,"%s: Left alone %ld articles (%ld bytes).  "
  237.                  "Total of %ld articles now use %ld bytes." ,
  238.                argv[0],
  239.                total_articles_kept,     total_bytes_kept,
  240.                total_articles_kept + total_articles_archived,
  241.                total_bytes_kept + total_bytes_archived );
  242.  
  243.    exit(0);
  244.  
  245. } /* main */
  246.  
  247. /*--------------------------------------------------------------------*/
  248. /*    E x p i r e A l l                                               */
  249. /*                                                                    */
  250. /*    Expire all defined news groups                                  */
  251. /*--------------------------------------------------------------------*/
  252.  
  253. static void ExpireAll( const time_t expire_date,
  254.                 const time_t archive_date )
  255. {
  256.    struct grp *cur_grp = group_list;
  257.  
  258.    while ( cur_grp != NULL )
  259.    {
  260.       ExpireOneGroup( cur_grp, expire_date, archive_date );
  261.                                     /* Clean up this group           */
  262.  
  263.       cur_grp = cur_grp->grp_next;  /* Then clean up the next group  */
  264.    }
  265. } /* Expire_All */
  266.  
  267. /*--------------------------------------------------------------------*/
  268. /*    E x p i r e G r o u p                                           */
  269. /*                                                                    */
  270. /*    Clean up one group by name                                      */
  271. /*--------------------------------------------------------------------*/
  272.  
  273. static void  ExpireGroup( const char *group,
  274.                       const time_t expire_date,
  275.                       const time_t archive_date )
  276. {
  277.    struct grp *cur_grp = group_list;
  278.    struct grp *target = NULL;
  279.  
  280. /*--------------------------------------------------------------------*/
  281. /*         Search the list of groups for the requested group          */
  282. /*--------------------------------------------------------------------*/
  283.  
  284.    while ( (cur_grp != NULL) && (target == NULL))
  285.    {
  286.       if ( equal( cur_grp->grp_name, group ))
  287.          target = cur_grp;
  288.  
  289.       cur_grp = cur_grp->grp_next;  /* Then clean up the next group  */
  290.    }
  291.  
  292. /*--------------------------------------------------------------------*/
  293. /*   If we found the group, process it, otherwise report the error    */
  294. /*--------------------------------------------------------------------*/
  295.  
  296.    if ( target == NULL )
  297.       printmsg(0,"Unable to locate active group %s", group );
  298.    else
  299.       ExpireOneGroup( target, expire_date, archive_date );
  300.                                     /* Clean up this group           */
  301.  
  302. } /* ExpireGroup */
  303.  
  304. /*--------------------------------------------------------------------*/
  305. /*    E x p i r e O n e G r o u p                                     */
  306. /*                                                                    */
  307. /*    Clean up one group by name                                      */
  308. /*--------------------------------------------------------------------*/
  309.  
  310. static void ExpireOneGroup( struct grp *cur_grp,
  311.                       const time_t expire_date,
  312.                       const time_t archive_date )
  313. {
  314.    char groupdir[FILENAME_MAX];
  315.    char archdir[FILENAME_MAX];
  316.  
  317.    printmsg(3,"Processing news group %s", cur_grp->grp_name );
  318.  
  319. /*--------------------------------------------------------------------*/
  320. /*                     Set up the directory names                     */
  321. /*--------------------------------------------------------------------*/
  322.  
  323.    ImportNewsGroup( groupdir, cur_grp->grp_name, 0 );
  324.    mkfilename( archdir, E_archivedir, &groupdir[ strlen( E_newsdir) + 1] );
  325.  
  326. /*--------------------------------------------------------------------*/
  327. /*            Process the primary and archive directories             */
  328. /*--------------------------------------------------------------------*/
  329.  
  330.    ExpireDirectory( cur_grp, archive_date, archdir, NULL);
  331.                               /* Purge archive first to keep
  332.                                  directory smaller                   */
  333.  
  334.    ExpireDirectory( cur_grp, expire_date, groupdir,
  335.                     (archive_date < expire_date) ? archdir : NULL);
  336.                               /* Do not archive for 0 days!          */
  337.  
  338. } /* ExpireOneGroup */
  339.  
  340. /*--------------------------------------------------------------------*/
  341. /*    E x p i r e D i r e c t o r y                                   */
  342. /*                                                                    */
  343. /*    Clean up one group by name                                      */
  344. /*--------------------------------------------------------------------*/
  345.  
  346. static void ExpireDirectory( struct grp *cur_grp,
  347.                       const time_t expire,
  348.                       const char *directory,
  349.                       const char *archive )
  350. {
  351.    char fname[FILENAME_MAX];
  352.  
  353.    int articles_archived = 0;/* Count of files moved to archive        */
  354.    int articles_purged   = 0;/* Count of files actually deleted        */
  355.    int articles_kept     = 0;/* Count of files actually deleted        */
  356.    long bytes_purged = 0;    /* Bytes freed on disk from deletions     */
  357.    long bytes_kept   = 0;    /* Bytes left on disk total               */
  358.    long bytes_archived = 0;  /* Bytes left on disk in archive          */
  359.  
  360.    boolean not_built = TRUE;  /* Did not insure archive directory
  361.                                  exists                           */
  362.  
  363.    long low = LONG_MAX;  /* Oldest article number left             */
  364.  
  365.    DIR *dirp;
  366.    struct direct *dp;
  367.  
  368. /*--------------------------------------------------------------------*/
  369. /*                Open up the directory for processing                */
  370. /*--------------------------------------------------------------------*/
  371.  
  372.    if ((dirp = opendirx(directory,"*.*")) == nil(DIR))
  373.    {
  374.       printmsg(3, "ExpireDirectory: couldn't opendir() %s", directory);
  375.       cur_grp->grp_low = cur_grp->grp_high;
  376.       return;
  377.    } /* if */
  378.  
  379. /*--------------------------------------------------------------------*/
  380. /*                 Switch to directory for processing                 */
  381. /*--------------------------------------------------------------------*/
  382.  
  383.    CHDIR( directory );
  384.  
  385. /*--------------------------------------------------------------------*/
  386. /*              Look for the next file in the directory               */
  387. /*--------------------------------------------------------------------*/
  388.  
  389.    while((dp = readdir(dirp)) != nil(struct direct))
  390.    {
  391.  
  392. /*--------------------------------------------------------------------*/
  393. /*                      Archive/expire this file?                     */
  394. /*--------------------------------------------------------------------*/
  395.  
  396.       if ( numeric( dp->d_name ))/* Article format name?             */
  397.       {                          /* Yes --> Examine it closer        */
  398.  
  399.          printmsg(6,"Processing file %s from %s",
  400.                   dp->d_name, dater( dp->d_modified, NULL));
  401.  
  402.          if ( dp->d_modified < expire )   /* Long in the tooth?      */
  403.          {                       /* Yes --> Move it on out           */
  404.             int not_processed = TRUE;
  405.                               /* Purge unless we archive it          */
  406.  
  407.             if ( archive != NULL )
  408.             {
  409.                printmsg( 4,"Archiving file %s from %s to %s",
  410.                         dp->d_name, directory , archive);
  411.  
  412.                if ( not_built )  /* First pass into directory?    */
  413.                {                 /* Yes --> Make sure it exists   */
  414.                   MKDIR( archive );
  415.                   not_built = FALSE;   /* Only build it once      */
  416.                }
  417.  
  418.                mkfilename( fname, archive, dp->d_name);
  419.                not_processed = rename( dp->d_name, fname );
  420.  
  421.                if ( not_processed )
  422.                {
  423.                   printerr( fname );
  424.                   printmsg(0,"Rename %s to %s failed, purging file.",
  425.                            dp->d_name, fname);
  426.                }
  427.                else {
  428.                   articles_archived++;
  429.                   bytes_archived += dp->d_size;
  430.                }
  431.             } /* if ( archive != NULL ) */
  432.  
  433.             if ( not_processed )
  434.             {
  435.                printmsg( 4,"Purging file %s from %s", dp->d_name, directory );
  436.                unlink( dp->d_name );
  437.                articles_purged++;
  438.                bytes_purged += dp->d_size;
  439.             } /* if ( not_processed ) */
  440.  
  441.          } /* if ( dp->d_modified < expire ) */
  442.  
  443. /*--------------------------------------------------------------------*/
  444. /*    If the article is valid and still in the main news              */
  445. /*    directory, determine if it is the lowest article left           */
  446. /*--------------------------------------------------------------------*/
  447.  
  448.          else {
  449.             long article = 0;
  450.             char *digit = dp->d_name;
  451.  
  452.             while( *digit )
  453.                article = article * 10 + (*digit++ - '0');
  454.  
  455.             low = min( article, low );
  456.  
  457.             bytes_kept += dp->d_size;
  458.             articles_kept ++;
  459.  
  460.          } /* else if ( archive != NULL ) */
  461.       } /* if ( numeric( dp->d_name ) */
  462.  
  463.    } /* while */
  464.  
  465. /*--------------------------------------------------------------------*/
  466. /*            Update lowest article available to the users            */
  467. /*--------------------------------------------------------------------*/
  468.  
  469.    if ( low == LONG_MAX )
  470.        cur_grp->grp_low = cur_grp->grp_high;
  471.    else
  472.        cur_grp->grp_low = low;
  473.  
  474. /*--------------------------------------------------------------------*/
  475. /*           Close up the directory and report what we did            */
  476. /*--------------------------------------------------------------------*/
  477.  
  478.    closedir(dirp);
  479.  
  480.    if ( articles_archived )
  481.       printmsg(2,"%s: Purged %d articles (%ld bytes),"
  482.                     " archived %d articles (%ld bytes),"
  483.                     " left alone %d articles (%ld bytes).",
  484.                   cur_grp->grp_name,
  485.                   articles_purged, bytes_purged,
  486.                   articles_archived, bytes_archived,
  487.                   articles_kept, bytes_kept );
  488.    else if ( articles_purged )
  489.       printmsg(2,"%s: Purged %d articles (%ld bytes),"
  490.                     " left alone %d articles (%ld bytes).",
  491.                   cur_grp->grp_name,
  492.                   articles_purged, bytes_purged,
  493.                   articles_kept, bytes_kept );
  494.    else if ( articles_kept )
  495.       printmsg(2,"%s: Left alone %d articles (%ld bytes).",
  496.                   cur_grp->grp_name,
  497.                   articles_kept, bytes_kept );
  498.  
  499.    total_articles_archived += articles_archived;
  500.    total_articles_kept     += articles_kept;
  501.    total_articles_purged   += articles_purged;
  502.    total_bytes_archived    += bytes_archived;
  503.    total_bytes_kept        += bytes_kept;
  504.    total_bytes_purged      += bytes_purged;
  505.  
  506. } /* ExpireDirectory */
  507.  
  508. /*--------------------------------------------------------------------*/
  509. /*    n u m e r i c                                                   */
  510. /*                                                                    */
  511. /*    Examines string, returns true if numeric with period            */
  512. /*--------------------------------------------------------------------*/
  513.  
  514.  static boolean numeric( char *start)
  515.  {
  516.    char *number = start;
  517.  
  518.    while (*number != '\0')
  519.    {
  520.       if (!isdigit(*number) && (*number != '.'))
  521.          return FALSE;
  522.  
  523.       number++;
  524.    }
  525.  
  526.    return TRUE;
  527.  } /* numeric */
  528.  
  529. /*--------------------------------------------------------------------*/
  530. /*    u s a g e                                                       */
  531. /*                                                                    */
  532. /*    Print usage of program                                          */
  533. /*--------------------------------------------------------------------*/
  534.  
  535. static void usage( void )
  536. {
  537.    printf( "Usage:   expire [-edays] [-adays] [-ngroup]\n");
  538.    exit(1);
  539. } /* usage */
  540.